package com.plpm.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.plpm.mapper.FileRecordMapper;
import com.plpm.model.FileRecord;
import com.plpm.vo.FileRecordVO;

import lombok.extern.slf4j.Slf4j;

/**
 * 文件记录服务类
 *
 * @author PLPM Team
 * @version 1.0
 */
@Slf4j
@Service
public class FileRecordService {

    @Autowired
    private FileRecordMapper fileRecordMapper;

    /**
     * 插入单个文件记录
     *
     * @param fileRecordVO 文件记录VO对象
     * @return 插入结果信息
     */
    public InsertResult insertFileRecord(FileRecordVO fileRecordVO) {
        try {
            // 参数验证
            if (fileRecordVO == null) {
                return InsertResult.error("插入数据不能为空");
            }

            log.info("开始插入文件记录，文件名: {}", fileRecordVO.getFileName());

            // 验证必要字段
            if (fileRecordVO.getFileName() == null || fileRecordVO.getFileName().trim().isEmpty()) {
                return InsertResult.error("文件名不能为空");
            }

            // 验证文件名是否已存在,根据同文件名且upload_status=1的记录
            FileRecordVO existingRecord = fileRecordMapper.findSuccessRecordByFileName(fileRecordVO.getFileName());
            if (existingRecord != null) {
                return InsertResult.error("file_record表中成功上传的同文件名已存在，无法插入");
            }

            // 将FileRecordVO转换为FileRecord
            FileRecord fileRecord = convertVOToEntity(fileRecordVO);

            // 创建方法：时间字段由前端设置并传递
            // createTime、updateTime、uploadTime 使用前端传递的值
            fileRecord.setCreateTime(fileRecordVO.getCreateTime());
            fileRecord.setUpdateTime(fileRecordVO.getUpdateTime());
            fileRecord.setUploadTime(fileRecordVO.getUploadTime());

            // 设置默认值
            setDefaultValues(fileRecord);
            
            // 日志记录，确认 createTime 已设置（使用 info 级别便于排查）
            log.info("准备插入文件记录，文件名: {}, createTime: {}, updateTime: {}, uploadTime: {}", 
                fileRecord.getFileName(), 
                fileRecord.getCreateTime(), 
                fileRecord.getUpdateTime(),
                fileRecord.getUploadTime());

            // 执行插入
            int insertCount = fileRecordMapper.insert(fileRecord);

            if (insertCount > 0) {
                log.info("文件记录插入成功，文件名: {}, projectNo: {}, engineNo: {}", 
                    fileRecordVO.getFileName(), fileRecord.getProjectNo(), fileRecord.getEngineNo());
                return InsertResult.success("文件记录插入成功", insertCount, fileRecordVO.getFileName());
            } else {
                log.warn("文件记录插入失败，insertCount=0，文件名: {}", fileRecordVO.getFileName());
                return InsertResult.error("文件记录插入失败");
            }

        } catch (Exception e) {
            log.error("插入文件记录时发生异常，文件名: {}", fileRecordVO != null ? fileRecordVO.getFileName() : "null", e);
            // 检查是否是UNIQUE约束冲突（文件名重复）
            if (e.getMessage() != null && (e.getMessage().contains("UNIQUE") || 
                e.getMessage().contains("unique") || e.getMessage().contains("duplicate"))) {
                return InsertResult.error("文件名已存在，无法重复插入: " + fileRecordVO.getFileName());
            }
            return InsertResult.error("插入文件记录时发生异常: " + e.getMessage());
        }
    }

    /**
     * 更新单个文件记录
     *
     * @param fileRecordVO 文件记录VO对象
     * @return 更新结果信息
     */
    public UpdateResult updateFileRecord(FileRecordVO fileRecordVO) {
        try {
            // 参数验证
            if (fileRecordVO == null) {
                return UpdateResult.error("更新数据不能为空");
            }

            log.info("开始更新文件记录，ID: {}", fileRecordVO.getId());

            // 验证ID字段
            if (fileRecordVO.getId() == null) {
                return UpdateResult.error("更新记录必须包含ID字段");
            }

            // 验证地点字段（如果提供）
            if (fileRecordVO.getPlace() != null && !fileRecordVO.getPlace().trim().isEmpty()) {
                String place = fileRecordVO.getPlace().trim();
                
                // 检查长度限制（最大50个字符）
                if (place.length() > 50) {
                    return UpdateResult.error("地点长度不能超过50个字符");
                }
                
                // 检查是否包含特殊字符（只允许中文、英文、数字、空格、连字符、下划线、括号）
                String validPattern = "^[\\u4e00-\\u9fa5a-zA-Z0-9\\s\\-_()（）]+$";
                if (!place.matches(validPattern)) {
                    return UpdateResult.error("地点只能包含中文、英文、数字、空格、连字符、下划线和括号");
                }
                
                // 检查是否包含连续的空格
                if (place.matches(".*\\s{2,}.*")) {
                    return UpdateResult.error("地点不能包含连续的空格");
                }
            }

            // 验证记录是否存在,根据同文件名且upload_status=1的记录
            FileRecordVO existingRecord = fileRecordMapper.findSuccessRecordByFileName(fileRecordVO.getFileName());
            if (existingRecord != null && !existingRecord.getId().equals(fileRecordVO.getId())) {
                return UpdateResult.error("file_record表中成功上传的同文件名，无法更新");
            }

            // 先根据ID查询原有记录，保持createTime不变
            FileRecordVO existingRecordVO = fileRecordMapper.findById(fileRecordVO.getId());
            if (existingRecordVO == null) {
                return UpdateResult.error("要更新的记录不存在");
            }
            
            // 将FileRecordVO转换为FileRecord
            FileRecord fileRecord = convertVOToEntity(fileRecordVO);

            // 更新方法：fileName 和 createTime 保留不更新（Mapper中已排除这些字段）
            // updateTime 和 uploadTime 使用前端传递的值
            fileRecord.setUpdateTime(fileRecordVO.getUpdateTime());
            fileRecord.setUploadTime(fileRecordVO.getUploadTime());
            
            // 保持原有的状态字段不变（如果前端没有传递这些字段）
            if (fileRecordVO.getSyncStatus() == null) {
                fileRecord.setSyncStatus(existingRecordVO.getSyncStatus());
            }
            if (fileRecordVO.getUploadStatus() == null) {
                fileRecord.setUploadStatus(existingRecordVO.getUploadStatus());
            }
            if (fileRecordVO.getRetryTime() == null) {
                fileRecord.setRetryTime(existingRecordVO.getRetryTime());
            }

            // 执行更新
            int updateCount = fileRecordMapper.update(fileRecord);

            if (updateCount > 0) {
                log.info("文件记录更新成功，ID: {}", fileRecordVO.getId());
                return UpdateResult.success("文件记录更新成功", updateCount, fileRecordVO.getId());
            } else {
                return UpdateResult.error("未找到要更新的记录或更新失败");
            }

        } catch (Exception e) {
            log.error("更新文件记录时发生异常，ID: {}", fileRecordVO != null ? fileRecordVO.getId() : "null", e);
            return UpdateResult.error("更新文件记录时发生异常: " + e.getMessage());
        }
    }

    /**
     * 批量更新文件记录
     *
     * @param fileRecordVOs 文件记录VO对象列表
     * @return 批量更新结果信息
     */
    @Transactional(rollbackFor = Exception.class)
    public BatchUpdateResult batchUpdateFileRecords(List<FileRecordVO> fileRecordVOs) {
        try {
            log.info("开始批量更新FileRecord记录，共{}条记录", fileRecordVOs.size());

            // 参数验证
            if (fileRecordVOs == null || fileRecordVOs.isEmpty()) {
                return BatchUpdateResult.error("批量更新数据不能为空");
            }

            // 验证每条记录的必要字段
            for (FileRecordVO recordVO : fileRecordVOs) {
                if (recordVO.getId() == null) {
                    return BatchUpdateResult.error("批量更新记录必须包含ID字段");
                }
                
                // 验证地点字段（如果提供）
                if (recordVO.getPlace() != null && !recordVO.getPlace().trim().isEmpty()) {
                    String place = recordVO.getPlace().trim();
                    
                    // 检查长度限制（最大50个字符）
                    if (place.length() > 50) {
                        return BatchUpdateResult.error("地点长度不能超过50个字符");
                    }
                    
                    // 检查是否包含特殊字符（只允许中文、英文、数字、空格、连字符、下划线、括号）
                    String validPattern = "^[\\u4e00-\\u9fa5a-zA-Z0-9\\s\\-_()（）]+$";
                    if (!place.matches(validPattern)) {
                        return BatchUpdateResult.error("地点只能包含中文、英文、数字、空格、连字符、下划线和括号");
                    }
                    
                    // 检查是否包含连续的空格
                    if (place.matches(".*\\s{2,}.*")) {
                        return BatchUpdateResult.error("地点不能包含连续的空格");
                    }
                }
            }

            // 将FileRecordVO转换为FileRecord
            List<FileRecord> fileRecords = convertVOToEntity(fileRecordVOs);

            // 更新方法：updateTime 和 uploadTime 使用前端传递的值，fileName 和 createTime 保留不更新（Mapper中已排除这些字段）
            // 使用索引循环，因为需要同时访问两个列表的对应元素
            for (int i = 0; i < fileRecords.size(); i++) {
                fileRecords.get(i).setUpdateTime(fileRecordVOs.get(i).getUpdateTime());
                fileRecords.get(i).setUploadTime(fileRecordVOs.get(i).getUploadTime());
            }
          
            // 执行批量更新 - 使用循环单条更新避免MyBatis参数映射问题
            int updateCount = 0;
            for (FileRecord record : fileRecords) {
                int result = fileRecordMapper.update(record);
                updateCount += result;
            }

            log.info("批量更新文件记录成功，共更新{}条记录", updateCount);
            return BatchUpdateResult.success("批量更新文件记录成功", updateCount, fileRecordVOs.size());

        } catch (Exception e) {
            log.error("批量更新文件记录时发生异常", e);
            return BatchUpdateResult.error("批量更新文件记录时发生异常: " + e.getMessage());
        }
    }

    /**
     * 批量插入文件记录
     *
     * @param fileRecordVOs 文件记录VO对象列表
     * @return 批量插入结果信息
     */
    public BatchInsertResult batchInsertFileRecords(List<FileRecordVO> fileRecordVOs) {
        try {
            log.info("开始批量插入文件记录，共{}条记录", fileRecordVOs != null ? fileRecordVOs.size() : 0);

            // 参数验证
            if (fileRecordVOs == null || fileRecordVOs.isEmpty()) {
                return BatchInsertResult.error("批量插入数据不能为空");
            }

            // 验证每条记录的必要字段
            for (FileRecordVO recordVO : fileRecordVOs) {
                if (recordVO.getFileName() == null || recordVO.getFileName().trim().isEmpty()) {
                    return BatchInsertResult.error("批量插入记录中文件名不能为空");
                }
            }

            // 检查文件名重复
            for (FileRecordVO recordVO : fileRecordVOs) {
                FileRecordVO existingRecord = fileRecordMapper.findSuccessRecordByFileName(recordVO.getFileName());
                if (existingRecord != null) {
                    return BatchInsertResult.error("file_record表中成功上传的同文件名，无法插入: " + recordVO.getFileName());
                }
            }

            // 将FileRecordVO转换为FileRecord
            List<FileRecord> fileRecords = convertVOToEntity(fileRecordVOs);

            // 创建方法：时间字段由前端设置并传递
            // createTime、updateTime、uploadTime 使用前端传递的值
            for (int i = 0; i < fileRecords.size(); i++) {
                FileRecord record = fileRecords.get(i);
                FileRecordVO vo = fileRecordVOs.get(i);
                record.setCreateTime(vo.getCreateTime());
                record.setUpdateTime(vo.getUpdateTime());
                record.setUploadTime(vo.getUploadTime());
                
                // 设置默认值
                setDefaultValues(record);
            }

            // 执行批量插入
            int insertCount = fileRecordMapper.batchInsert(fileRecords);

            log.info("批量插入文件记录成功，共插入{}条记录", insertCount);
            return BatchInsertResult.success("批量插入文件记录成功", insertCount, fileRecordVOs.size());

        } catch (Exception e) {
            log.error("批量插入文件记录时发生异常", e);
            return BatchInsertResult.error("批量插入文件记录时发生异常: " + e.getMessage());
        }
    }

    /**
     * 设置FileRecord的默认值
     */
    private void setDefaultValues(FileRecord record) {
        if (record.getUploadStatus() == null) {
            //上传状态需要等FileUpload.js中的saveFileRecordToDatabase方法中的uploadStatus赋值
            record.setUploadStatus(1); // 默认上传成功
        }
        // syncStatus 保持为 null，不设置默认值
        if (record.getRetryTime() == null) {
            record.setRetryTime(0); // 默认重试次数为0
        }
        if (record.getSyncDataSource() == null) {
            record.setSyncDataSource(0); // 默认大东
        }
    }

    /**
     * 将FileRecordVO转换为FileRecord（通用方法）
     */
    private FileRecord convertVOToEntity(FileRecordVO vo) {
        if (vo == null) {
            return null;
        }

        FileRecord record = new FileRecord();
        record.setId(vo.getId());
        record.setFileName(vo.getFileName());
        record.setProjectNo(vo.getProjectNo());
        record.setPlaneId(vo.getPlaneId());
        record.setPlaneNo(vo.getPlaneNo());
        record.setPlace(vo.getPlace());
        record.setCompany(vo.getCompany());
        record.setProductPhase(vo.getProductPhase());
        record.setDataTypeFirst(vo.getDataTypeFirst());
        record.setDataTypeSecond(vo.getDataTypeSecond());
        record.setDataSource(vo.getDataSource());
        record.setStartTime(vo.getStartTime());
        record.setEngineId(vo.getEngineId());
        record.setEngineNo(vo.getEngineNo());
        record.setChannelNo(vo.getChannelNo());
        record.setDeviceNo(vo.getDeviceNo());
        record.setEnginePlace(vo.getEnginePlace());
        record.setEcuId(vo.getEcuId());
        record.setEcuNo(vo.getEcuNo());
        record.setEcuSysId(vo.getEcuSysId());
        record.setEcuSysNo(vo.getEcuSysNo());
        record.setSubject(vo.getSubject());
        record.setRemark(vo.getRemark());
        record.setCheckCode(vo.getCheckCode());
        record.setSyncDataSource(vo.getSyncDataSource());
        record.setSyncStatus(vo.getSyncStatus());
        record.setUploadStatus(vo.getUploadStatus());
        // 时间字段不在公用方法中设置，由调用方根据业务需求处理
        // createTime、updateTime、uploadTime 由前端设置并传递，或者由调用方根据业务逻辑设置
        record.setRetryTime(vo.getRetryTime());

        return record;
    }

    /**
     * 批量将FileRecordVO转换为FileRecord
     */
    private List<FileRecord> convertVOToEntity(List<FileRecordVO> fileRecordVOs) {
        if (fileRecordVOs == null || fileRecordVOs.isEmpty()) {
            return new ArrayList<>();
        }

        List<FileRecord> fileRecords = new ArrayList<>();
        for (FileRecordVO vo : fileRecordVOs) {
            FileRecord record = convertVOToEntity(vo);
            if (record != null) {
                fileRecords.add(record);
            }
        }

        return fileRecords;
    }

    /**
     * 插入结果内部类
     */
    public static class InsertResult {
        private final boolean success;
        private final String message;
        private final int insertCount;
        private final String fileName;

        private InsertResult(boolean success, String message, int insertCount, String fileName) {
            this.success = success;
            this.message = message;
            this.insertCount = insertCount;
            this.fileName = fileName;
        }

        public static InsertResult success(String message, int insertCount, String fileName) {
            return new InsertResult(true, message, insertCount, fileName);
        }

        public static InsertResult error(String message) {
            return new InsertResult(false, message, 0, null);
        }

        // Getters
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
        public int getInsertCount() { return insertCount; }
        public String getFileName() { return fileName; }
    }

    /**
     * 批量插入结果内部类
     */
    public static class BatchInsertResult {
        private final boolean success;
        private final String message;
        private final int insertCount;
        private final int totalCount;

        private BatchInsertResult(boolean success, String message, int insertCount, int totalCount) {
            this.success = success;
            this.message = message;
            this.insertCount = insertCount;
            this.totalCount = totalCount;
        }

        public static BatchInsertResult success(String message, int insertCount, int totalCount) {
            return new BatchInsertResult(true, message, insertCount, totalCount);
        }

        public static BatchInsertResult error(String message) {
            return new BatchInsertResult(false, message, 0, 0);
        }

        // Getters
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
        public int getInsertCount() { return insertCount; }
        public int getTotalCount() { return totalCount; }
    }

    /**
     * 更新结果内部类
     */
    public static class UpdateResult {
        private final boolean success;
        private final String message;
        private final int updateCount;
        private final Long recordId;

        private UpdateResult(boolean success, String message, int updateCount, Long recordId) {
            this.success = success;
            this.message = message;
            this.updateCount = updateCount;
            this.recordId = recordId;
        }

        public static UpdateResult success(String message, int updateCount, Long recordId) {
            return new UpdateResult(true, message, updateCount, recordId);
        }

        public static UpdateResult error(String message) {
            return new UpdateResult(false, message, 0, null);
        }

        // Getters
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
        public int getUpdateCount() { return updateCount; }
        public Long getRecordId() { return recordId; }
    }

    /**
     * 批量更新结果内部类
     */
    public static class BatchUpdateResult {
        private final boolean success;
        private final String message;
        private final int updateCount;
        private final int totalCount;

        private BatchUpdateResult(boolean success, String message, int updateCount, int totalCount) {
            this.success = success;
            this.message = message;
            this.updateCount = updateCount;
            this.totalCount = totalCount;
        }

        public static BatchUpdateResult success(String message, int updateCount, int totalCount) {
            return new BatchUpdateResult(true, message, updateCount, totalCount);
        }

        public static BatchUpdateResult error(String message) {
            return new BatchUpdateResult(false, message, 0, 0);
        }

        // Getters
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
        public int getUpdateCount() { return updateCount; }
        public int getTotalCount() { return totalCount; }
    }
}
